package org.agilelang.generator.javastruts2;

/*
 AgileLang - A fourth generation language(http://www.agilelang.org).

 Copyright (C) 2013 Roderick Cusirramos (roderick20@hotmail.com)

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.agilelang.mvc.Generator;
import org.agilelang.mvc.IModel;
import org.agilelang.object.Model;
import org.agilelang.object.Project;
import org.agilelang.object.attributes.Attribute;
import org.agilelang.object.attributes.Reference;

public class GModel extends Generator implements IModel {

    Map typeData = new HashMap();
    String catalog = "";

    public GModel(String path, Project project) {
        this.appName = project.application.name;
        this.path = path;
        this.models = project.models;
        this.catalog = project.application.database;
        this.template2="javastruts2";
        //this.listScaffold = project.scaffolds;

        typeData.put("string", "String");
        typeData.put("text", "String");
        typeData.put("integer", "int");
        typeData.put("int", "int");
        typeData.put("float", "float");
        typeData.put("datetime", "Date");
        typeData.put("timestamp", "Date");
        typeData.put("time", "Date");
        typeData.put("date", "java.util.Date");
        typeData.put("binary", "int");
        typeData.put("boolean", "boolean");
    }

    public void process() {
        model();
        mapping();
        entitis();
    }

    public void model() {
        int t = models.size();
        for (int i = 0; i < t; i++) {
            Model controller = models.get(i);
            List<Attribute> attrs = controller.attributes;
            int tt = attrs.size();
            String param_attrs = "";
            String asign_attrs = "";
            for (int j = 0; j < tt; j++) {
                Attribute attr = attrs.get(j);
                String NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                param_attrs = param_attrs + "," + getTypeData(attr.type) + " " + attr.name;
                asign_attrs = asign_attrs + "\t\t\t" + controller.name.toLowerCase() + ".set" + NameAtrr + "(" + attr.name + ");\r\n";
            }

            String file = readStreamTpl("m_model.java.tpl");
            file = file.replace("//nameClass//", controller.name);
            file = file.replace("//nameclass//", controller.name.toLowerCase());
            file = file.replace("//nameparam//", param_attrs);
            file = file.replace("//nameasing//", asign_attrs);

            createfile("src/java/model/" + controller.name + "Model.java", path, file);

            file = readStreamTpl("m_dao.java.tpl");
            file = file.replace("//nameClass//", controller.name);
            createfile("src/java/model/dao/" + controller.name + "DAO.java", path, file);
        }
        //String file = readStreamTpl("m_HibernateUtil.java.tpl");
        //createfile("src/java/model/HibernateUtil.java", path, file);
    }

    public void mapping() {
        String reveng = "";
        String cfg = "";
        int t = models.size();
        for (int i = 0; i < t; i++) {
            Model model = models.get(i);
            //String NameClass = scaffold.name.substring(0, 1).toUpperCase() + scaffold.name.substring(1, scaffold.name.length());
            reveng = reveng + "\t<table-filter match-name=\"" + model.name.toLowerCase() + "\"/>\r\n";
            cfg = cfg + "\t<mapping resource=\"model/mapping/" + model.name + ".hbm.xml\"/>\r\n";
            List<Attribute> attrs = model.attributes;
            int tt = attrs.size();
            String str_attrs = "";
            for (int j = 0; j < tt; j++) {
                Attribute attr = attrs.get(j);
                if(!attr.name.equals("id") &&  !attr.name.endsWith("_id") ){
                    str_attrs = str_attrs //length=\"255\"
                        + "\t\t<property name=\"" + attr.name + "\" type=\"" + attr.type + "\">\r\n"
                        + "\t\t\t<column  name=\"" + attr.name + "\" />\r\n"//not-null=\"true\"
                        + "\t\t</property>\r\n";
                }
                
            }

            List<Reference> references = model.references;
            tt = references.size();
            String str_references = "";
            for (int j = 0; j < tt; j++) {
                Reference reference = references.get(j);
                str_references +=
                        "\t\t<many-to-one class=\"model.entities." + reference.model_reference + "\" fetch=\"select\" name=\"" + reference.model_reference.toLowerCase() + "\">\r\n"
                        + "\t\t\t<column name=\"" + reference.foreign_key + "\"/>\r\n"
                        + "\t\t</many-to-one>\r\n";
            }
            tt = models.size();
            String str_references2 = "";
            for (int jj = 0; jj < tt; jj++) {
                Model model2 = models.get(jj);
                List<Reference> references2 = model2.references;
                int tt2 = references2.size();

                for (int k = 0; k < tt2; k++) {
                    Reference reference2 = references2.get(k);
                    if (reference2.model_reference.equals(model.name)) {
                        str_references2 +=
                                "\t\t<set inverse=\"true\" name=\"" + this.setPluralize(model2.name).toLowerCase() + "\">\r\n"
                                + "\t\t\t<key>\r\n"
                                + "\t\t\t\t<column name=\"" + reference2.foreign_key + "\"/>\r\n"
                                + "\t\t\t</key>\r\n"
                                + "\t\t\t<one-to-many class=\"model.entities." + model2.name + "\"/>\r\n"
                                + "\t\t</set>\r\n";
                    }
                }
            }
            String fileclass =
                    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
                    + "<!DOCTYPE hibernate-mapping PUBLIC \"-//Hibernate/Hibernate Mapping DTD 3.0//EN\" \"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd\">\r\n"
                    + "<hibernate-mapping>\r\n"
                    + "\t<class catalog=\"" + this.catalog + "\" name=\"model.entities." + model.name + "\" table=\"" + model.table + "\">\r\n"
                    + "\t\t<id name=\"id\" type=\"java.lang.Integer\">\r\n"
                    + "\t\t\t<column name=\"id\"/>\r\n"
                    + "\t\t\t<generator class=\"identity\"/>\r\n"
                    + "\t\t</id>\r\n"
                    + str_references
                    + str_attrs
                    + str_references2
                    + "\t</class>\r\n"
                    + "</hibernate-mapping>";
            createfile("src/java/model/mapping/" + model.name + ".hbm.xml", path, fileclass);
        }


        //----------------------------------------------------------------------
        /*String file = readStreamTpl("m_hibernate.reveng.xml.tpl");
        file = file.replace("//appname//", this.appName.toLowerCase());
        file = file.replace("//table//", reveng);
        createfile("src/java/model/mapping/hibernate.reveng.xml", path, file);*/
        //----------------------------------------------------------------------
        String file_cfg = readStreamTpl("m_hibernate.cfg.xml.tpl");
        file_cfg = file_cfg.replace("//catalog//", this.catalog);
        file_cfg = file_cfg.replace("//mapping//", cfg);
        createfile("src/java/hibernate.cfg.xml", path, file_cfg);
        //----------------------------------------------------------------------
    }

    public void entitis() {
        String NameAtrr = "";
        int t = models.size();
        for (int i = 0; i < t; i++) {
            Model model = models.get(i);
            //String NameClass = scaffold.name.substring(0, 1).toUpperCase() + scaffold.name.substring(1, scaffold.name.length());

            List<Attribute> attrs = model.attributes;
            int tt = attrs.size();
            String str_attrs = "";
            String str_funct = "";
            for (int j = 0; j < tt; j++) {
                Attribute attr = attrs.get(j);
                if (attr.type.equals("string") || attr.type.equals("text")) {
                    str_attrs = str_attrs + "\tprivate String " + attr.name + "; \r\n";
                    NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                    str_funct = str_funct + "\tpublic String get" + NameAtrr + "() {\r\n"
                            + "\t\treturn this." + attr.name + ";\r\n"
                            + "\t}\r\n"
                            + "\tpublic void set" + NameAtrr + "(String " + attr.name + ") {\r\n"
                            + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
                            + "\t}\r\n";
                }
                if (attr.type.equals("boolean")) {
                    str_attrs = str_attrs + "\tprivate boolean " + attr.name + "; \r\n";
                    NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                    str_funct = str_funct + "\tpublic boolean get" + NameAtrr + "() {\r\n"
                            + "\t\treturn this." + attr.name + ";\r\n"
                            + "\t}\r\n"
                            + "\tpublic void set" + NameAtrr + "(boolean " + attr.name + ") {\r\n"
                            + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
                            + "\t}\r\n";
                }
                if (attr.type.equals("double")) {
                    str_attrs = str_attrs + "\tprivate Double " + attr.name + "; \r\n";
                    NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                    str_funct = str_funct + "\tpublic Double get" + NameAtrr + "() {\r\n"
                            + "\t\treturn this." + attr.name + ";\r\n"
                            + "\t}\r\n"
                            + "\tpublic void set" + NameAtrr + "(Double " + attr.name + ") {\r\n"
                            + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
                            + "\t}\r\n";
                }
                if (((attr.type.equals("int") || attr.type.equals("integer"))) && !attr.name.equals("id")){
                    str_attrs = str_attrs + "\tprivate Integer " + attr.name + "; \r\n";
                    NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                    str_funct = str_funct + "\tpublic Integer get" + NameAtrr + "() {\r\n"
                            + "\t\treturn this." + attr.name + ";\r\n"
                            + "\t}\r\n"
                            + "\tpublic void set" + NameAtrr + "(Integer " + attr.name + ") {\r\n"
                            + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
                            + "\t}\r\n";
                }
                if (attr.type.equals("decimal")) {
                    str_attrs = str_attrs + "\tprivate BigDecimal " + attr.name + "; \r\n";
                    NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                    str_funct = str_funct + "\tpublic BigDecimal get" + NameAtrr + "() {\r\n"
                            + "\t\treturn this." + attr.name + ";\r\n"
                            + "\t}\r\n"
                            + "\tpublic void set" + NameAtrr + "(BigDecimal " + attr.name + ") {\r\n"
                            + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
                            + "\t}\r\n";
                }
                if (attr.type.equals("date")) {
                    str_attrs = str_attrs + "\tprivate java.util.Date " + attr.name + "; \r\n";
                    NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
                    str_funct = str_funct + "\tpublic java.util.Date get" + NameAtrr + "() {\r\n"
                            + "\t\treturn this." + attr.name + ";\r\n"
                            + "\t}\r\n"
                            + "\tpublic void set" + NameAtrr + "(java.util.Date " + attr.name + ") {\r\n"
                            + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
                            + "\t}\r\n";
                }
            }

            List<Reference> references = model.references;
            tt = references.size();
            String str_references = "";
            for (int j = 0; j < tt; j++) {
                Reference reference = references.get(j);
                str_attrs +=
                        "\tprivate " + reference.model_reference + " " + reference.model_reference.toLowerCase() + "; \r\n";
                str_funct = str_funct + "\tpublic " + reference.model_reference + " get" + reference.model_reference + "() {\r\n"
                        + "\t\treturn this." + reference.model_reference.toLowerCase() + ";\r\n"
                        + "\t}\r\n"
                        + "\tpublic void set" + reference.model_reference + "(" + reference.model_reference + " " + reference.model_reference.toLowerCase() + ") {\r\n"
                        + "\t\tthis." + reference.model_reference.toLowerCase() + " = " + reference.model_reference.toLowerCase() + ";\r\n"
                        + "\t}\r\n";
            }
            
            tt = models.size();
            String str_references2 = "";
            for (int jj = 0; jj < tt; jj++) {
                Model model2 = models.get(jj);
                List<Reference> references2 = model2.references;
                int tt2 = references2.size();

                for (int k = 0; k < tt2; k++) {
                    Reference reference2 = references2.get(k);
                    if (reference2.model_reference.equals(model.name)) {
                        
                        str_attrs = str_attrs + "\tprivate Set " + this.setPluralize(model2.name).toLowerCase() + " = new HashSet(0); \r\n";
                        
                        str_funct = str_funct + "\tpublic Set get" + this.setPluralize(model2.name) + "() {\r\n"
                        + "\t\treturn this." + this.setPluralize(model2.name).toLowerCase() + ";\r\n"
                        + "\t}\r\n"
                        + "\tpublic void set" + this.setPluralize(model2.name) + "( Set " + this.setPluralize(model2.name).toLowerCase() + ") {\r\n"
                        + "\t\tthis." + this.setPluralize(model2.name).toLowerCase() + " = " + this.setPluralize(model2.name).toLowerCase() + ";\r\n"
                        + "\t}\r\n";
                        
                        
                        str_references2 +=
                                "\t\t<set inverse=\"true\" name=\"" + this.setPluralize(model2.name).toLowerCase() + "\">\r\n"
                                + "\t\t\t<key>\r\n"
                                + "\t\t\t\t<column name=\"" + reference2.foreign_key + "\"/>\r\n"
                                + "\t\t\t</key>\r\n"
                                + "\t\t\t<one-to-many class=\"model.entities." + model2.name + "\"/>\r\n"
                                + "\t\t</set>\r\n";
                    }
                }
            }
            
            String fileclass = "package model.entities;\r\n\r\n"
                    + "import java.util.HashSet;\r\n"
                    + "import java.util.Set;\r\n\r\n"
                    + "public class " + model.name + " implements java.io.Serializable \r\n{\r\n"
                    + "\tprivate Integer id;\r\n"
                    + str_attrs
                    + "\tpublic " + model.name + "() {\r\n"
                    + "\t}\r\n"
                    + "\tpublic Integer getId() {\r\n"
                    + "\t\treturn this.id;\r\n"
                    + "\t}\r\n"
                    + "\tpublic void setId(Integer id) {\r\n"
                    + "\t\tthis.id = id;\r\n"
                    + "\t}\r\n"
                    + str_funct
                    + "}";

            createfile("src/java/model/entities/" + model.name + ".java", path, fileclass);
        }


        /* t = this.scaffols.size();
       
         for (int i = 0; i < t; i++) {
         Scaffold scaffold = this.scaffols.get(i);
         String NameClass = scaffold.name.substring(0, 1).toUpperCase() + scaffold.name.substring(1, scaffold.name.length());

         List<Attribute> attrs = scaffold.attributes;
         int tt = attrs.size();
         String str_attrs = "";
         String str_funct = "";
         for (int j = 0; j < tt; j++) {
         Attribute attr = attrs.get(j);
         if (attr.type.equals("string") || attr.type.equals("text")) {
         str_attrs = str_attrs + "\tprivate String " + attr.name + "; \r\n";
         NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
         str_funct = str_funct + "\tpublic String get" + NameAtrr + "() {\r\n"
         + "\t\treturn this." + attr.name + ";\r\n"
         + "\t}\r\n"
         + "\tpublic void set" + NameAtrr + "(String " + attr.name + ") {\r\n"
         + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
         + "\t}\r\n";
         }
         if (attr.type.equals("boolean")) {
         str_attrs = str_attrs + "\tprivate boolean " + attr.name + "; \r\n";
         NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
         str_funct = str_funct + "\tpublic boolean get" + NameAtrr + "() {\r\n"
         + "\t\treturn this." + attr.name + ";\r\n"
         + "\t}\r\n"
         + "\tpublic void set" + NameAtrr + "(boolean " + attr.name + ") {\r\n"
         + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
         + "\t}\r\n";
         }
         if (attr.type.equals("int")) {
         str_attrs = str_attrs + "\tprivate Integer " + attr.name + "; \r\n";
         NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
         str_funct = str_funct + "\tpublic Integer get" + NameAtrr + "() {\r\n"
         + "\t\treturn this." + attr.name + ";\r\n"
         + "\t}\r\n"
         + "\tpublic void set" + NameAtrr + "(Integer " + attr.name + ") {\r\n"
         + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
         + "\t}\r\n";
         }
         if (attr.type.equals("decimal")) {
         str_attrs = str_attrs + "\tprivate BigDecimal " + attr.name + "; \r\n";
         NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
         str_funct = str_funct + "\tpublic BigDecimal get" + NameAtrr + "() {\r\n"
         + "\t\treturn this." + attr.name + ";\r\n"
         + "\t}\r\n"
         + "\tpublic void set" + NameAtrr + "(BigDecimal " + attr.name + ") {\r\n"
         + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
         + "\t}\r\n";
         }
         if (attr.type.equals("date")) {
         str_attrs = str_attrs + "\tprivate java.util.Date " + attr.name + "; \r\n";
         NameAtrr = attr.name.substring(0, 1).toUpperCase() + attr.name.substring(1, attr.name.length());
         str_funct = str_funct + "\tpublic java.util.Date get" + NameAtrr + "() {\r\n"
         + "\t\treturn this." + attr.name + ";\r\n"
         + "\t}\r\n"
         + "\tpublic void set" + NameAtrr + "(java.util.Date " + attr.name + ") {\r\n"
         + "\t\tthis." + attr.name + " = " + attr.name + ";\r\n"
         + "\t}\r\n";
         }
         }
         String fileclass = "package model.entities;\r\n"
         + "public class " + NameClass + " implements java.io.Serializable \r\n{\r\n"
         + "\tprivate Integer id;\r\n"
         + str_attrs
         + "\tpublic " + NameClass + "() {\r\n"
         + "\t}\r\n"
         + "\tpublic Integer getId() {\r\n"
         + "\t\treturn this.id;\r\n"
         + "\t}\r\n"
         + "\tpublic void setId(Integer id) {\r\n"
         + "\t\tthis.id = id;\r\n"
         + "\t}\r\n"
         + str_funct
         + "}";

         createfile("src/java/model/entities/" + NameClass + ".java", path, fileclass);
         }*/

    }

    public String getTypeData(String type) {
        return (String) typeData.get(type);
    }
}
